//||=========================================================================||
//||                                                                         ||
//||                             CudaCounter.cpp                             ||
//||                                                                         ||
//||                           by the_best_goose))                           ||
//||                                                                         ||
//||=========================================================================||

#include <assert.h>
#include "CudaCounter.h"
#include "FastComplex.cpp"

//-----------------------------------------------------------------------------

CudaCounter::CudaCounter(const MainWindow* pwind, const QWidget* pmand_pic):
    MandelbrotCounter(pwind, pmand_pic),
    pcuda_count_func_(NULL)
{
}

//-----------------------------------------------------------------------------

CudaCounter::~CudaCounter()
{
}

//-----------------------------------------------------------------------------

void CudaCounter::run()
{
    assert(is_valid_);
    assert(pcuda_count_func_);
    assert(pixels_);

    pcuda_count_func_(FastComplex(t_.x(), t_.y()), iter_points_arr_,
                                  iter_points_count_,
                                  graph_rect_.left(), graph_rect_.right(), 
                                  graph_rect_.bottom(), graph_rect_.top(),
                                  iters_, (int*)pixels_, 
                                  px_size_.width(), px_size_.height());
    for(int i = 0; i < px_size_.width() * px_size_.height(); ++i)
        pixels_[i] = index_array_[pixels_[i]];
    emit Counted();
}

//-----------------------------------------------------------------------------

void CudaCounter::GenerateFile()
{
    string to_append
            ("\n__device__ void Iterate(FastComplex& z, FastComplex& c,"
             "FastComplex& t){\n    z = ");
    to_append += GenFormula();
    to_append += string(";\n}\n\n");
    QFile::remove("gen/LastGeneratedCounter.cu");
    QFile::copy ("gen/CudaCounterTemplate.cu", "gen/LastGeneratedCounter.cu");
    QFile gen("gen/LastGeneratedCounter.cu");
    assert(gen.open(QIODevice::Append));
    gen.write(to_append.c_str());
    gen.close();
}

//-----------------------------------------------------------------------------

void CudaCounter::CompileFile()
{
    string for_call = "nvcc --cuda gen/LastGeneratedCounter.cu "
                      "--compiler-bindir=/home/the-best-goose/gcc44/ "
                      "-o gen/LastGeneratedCounter.cu.cpp;"
                      "g++ -fpermissive"
                      " -fpic -c gen/LastGeneratedCounter.cu.cpp "
                      "-o gen/LastGeneratedCounter.o; g++ -shared -o \"gen/lib";
    for_call += file_name_;
    for_call += ".so\" gen/LastGeneratedCounter.o\n";
    system(for_call.c_str());
    assert(QLibrary::isLibrary((string("gen/lib") + file_name_ + string(".so")).
                                                                     c_str()));
}

//-----------------------------------------------------------------------------

void CudaCounter::LoadLibrary()
{
    lib_.unload();
    lib_.setFileName((string("gen/lib") + file_name_.c_str() + string(".so")).
     		                                                          c_str());
    lib_.load();
    assert(lib_.isLoaded());
    pcuda_count_func_ = (CudaCountFunc) lib_.resolve("CountMandelbrot");
    assert(pcuda_count_func_);
}


